/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.servlet;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.vos.EnvVo;
import cn.easyplatform.spi.service.IdentityService;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.web.WebApps;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.service.ServiceLocator;
import cn.easyplatform.web.task.BackendException;
import cn.easyplatform.web.utils.WebUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.zkoss.web.servlet.http.Https;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLDecoder;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class DownloadServlet extends HttpServlet {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doPost(req, resp);
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String fn = req.getParameter("id");
        if (!Strings.isBlank(fn)) {
            try {
                fn = URLDecoder.decode(fn, "utf8");
                //fn = new String(fn.getBytes("ISO-8859-1"), "utf8");
                EnvVo env = (EnvVo) req.getSession().getAttribute(Contexts.PLATFORM_APP_ENV);
                byte[] data = null;
                if (env != null) {
                    try {
                        data = getRealFile(env, req.getSession(), fn);
                    } catch (BackendException ex) {
                        outputError(resp, ex.getMsg().getCode() + ex.getMsg().getBody());
                        return;
                    } catch (Exception ex) {
                        outputError(resp, FilenameUtils.getName(fn) + " not found.");
                        return;
                    }
                } else if (req.getParameter("token") != null || req.getHeader("token") != null) {
                    String token = req.getParameter("token");
                    if (token == null)
                        token = req.getHeader("token");
                    try {
                        data = getRealFile(token, req.getSession(), fn);
                    } catch (BackendException ex) {
                        outputError(resp, ex.getMsg().getCode() + ex.getMsg().getBody());
                        return;
                    } catch (Exception ex) {
                        outputError(resp, FilenameUtils.getName(fn) + " not found.");
                        return;
                    }
                } else {
                    File file = new File(WebApps.getRealPath(fn));
                    if (!file.exists()) {
                        outputError(resp, FilenameUtils.getName(fn) + " not found.");
                        return;
                    }
                    data = FileUtils.readFileToByteArray(file);
                }
                resp.setContentType("application/octet-stream;charset=utf-8");
                resp.addHeader("Pragma", "No-cache");
                resp.addHeader("Cache-Control", "No-cache");
                resp.setDateHeader("Expires", 0);
                resp.addHeader("content-type", "application/octet-stream");
                OutputStream os = resp.getOutputStream();
                if (data.length > 200) {
                    byte[] bs = Https.gzip(req, resp, null, data);
                    if (bs != null)
                        data = bs; //yes, browser support compress
                }
                resp.setContentLength(data.length);
                os.write(data);
                resp.flushBuffer();
                os.close();
            } catch (Exception ex) {
                outputError(resp, FilenameUtils.getName(fn) + " not found.");
            }
        } else {
            outputError(resp, "read error,invalid url.");
        }
    }

    private void outputError(HttpServletResponse response, String message) {
        response.addHeader("Expires", "0");
        response.addHeader("Cache-Control",
                "no-store, no-cache, must-revalidate");
        response.addHeader("Content-Type", "text/html; charset=utf-8");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.addHeader("Pragma", "no-cache");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.write(message);
            out.flush();
        } catch (Exception ex) {
        } finally {
            try {
                out.close();
                out = null;
            } catch (Exception ex) {
            }
        }
    }

    private byte[] getRealFile(Object obj, HttpSession session, String fn) {
        EnvVo env = null;
        String userId = null;
        if (obj instanceof EnvVo) {
            env = (EnvVo) obj;
            userId = Contexts.getUser(session).getId();
        } else {
            IdentityService as = ServiceLocator.lookup(IdentityService.class);
            SimpleRequestMessage req = new SimpleRequestMessage();
            req.setSessionId((Serializable) obj);
            IResponseMessage<?> resp = as.getAppEnv(req);
            if (!resp.isSuccess())
                throw new BackendException(resp);
            env = (EnvVo) resp.getBody();
            userId = env.getAppContext();
        }
        return WebUtils.getFileContent(env, userId, fn);
    }
}
